package conn

import (
	"gitee.com/injoyai/goutil/oss/io"
	"log"
	"net"
	"strings"
	"time"
)

// Dial 连接
func Dial(network, addr string) (*Conn, error) {
	var dial func() (io.ReadWriteCloser, error)
	switch strings.ToLower(network) {
	case "udp":
		udpAddr, err := net.ResolveUDPAddr("udp", addr)
		if err != nil {
			return nil, err
		}
		dial = func() (io.ReadWriteCloser, error) { return net.DialUDP("udp", nil, udpAddr) }
	default:
		dial = func() (io.ReadWriteCloser, error) { return net.Dial(network, addr) }
	}
	c, err := io.NewDial(dial)
	if err == nil {
		//设置远程地址为唯一标识
		c.SetKey(c.Interface().(net.Conn).RemoteAddr().String())
	}
	return c, err
}

// DialUDP 连接UDP
func DialUDP(addr string) (*Conn, error) {
	return Dial("udp", addr)
}

// DialTCP 连接TCP
func DialTCP(addr string) (*Conn, error) {
	return Dial("tcp", addr)
}

// MustDial
// 尝试连接直至成功,1次,断开不会重连
// 采用退避重试,2s-32s,倍数增长
func MustDial(network, addr string) *Conn {
	t := time.Second
again:
	c, err := Dial(network, addr)
	if err != nil {
		if t < time.Second*30 {
			t = 2 * t
		}
		log.Printf("[错误][%s] %s,等待%s秒重试", addr, err.Error(), t)
		time.Sleep(t)
		goto again
	}
	return c
}

// MustDialTCP 连接TCP直到成功
func MustDialTCP(addr string) *Conn {
	return MustDial("tcp", addr)
}

// MustDialUDP 连接UDP直到成功
func MustDialUDP(addr string) *Conn {
	return MustDial("udp", addr)
}

// Redial 重试连接
func Redial(network, addr string, fn ...func(c *io.Client)) *Conn {
	c := MustDial(network, addr)
	c.Redial(fn...)
	return c
}

// RedialTCP 重试连接TCP
func RedialTCP(addr string, fn ...func(c *io.Client)) *Conn {
	return Redial("tcp", addr, fn...)
}

// RedialUDP 重试连接UDP
func RedialUDP(addr string, fn ...func(c *io.Client)) *Conn {
	return Redial("udp", addr, fn...)
}
